use std::any::Any;
use std::marker::PhantomData;

use crate::id::Id;
use crate::message::EventResult;
use crate::sequence::{PodSlice, ViewMarker, ViewSequence};
use crate::view::{Cx, View};
use crate::widget::ChangeFlags;

pub struct HorizontalLayout<T, A, VS: ViewSequence<T, A>> {
    children: VS,
    _phantom_data: PhantomData<(A, T)>,
}

impl<T, A, VS: ViewSequence<T, A>> HorizontalLayout<T, A, VS> {
    pub fn new(views: VS) -> Self {
        Self {
            children: views,
            _phantom_data: Default::default(),
        }
    }
}

impl<T, A, VS: ViewSequence<T, A>> ViewMarker for HorizontalLayout<T, A, VS> {}

impl<T, A, VS: ViewSequence<T, A>> View<T, A> for HorizontalLayout<T, A, VS> {
    type State = VS::State;
    type Element = crate::widget::HorizontalLayout;

    fn build(&self, cx: &mut Cx) -> (Id, Self::State, Self::Element) {
        let mut els = vec![];
        let (id, state) = cx.with_new_id(|cx| self.children.build(cx, &mut els));
        let vl = crate::widget::HorizontalLayout::new(els);
        (id, state, vl)
    }

    fn rebuild(
        &self,
        prev: &Self,
        cx: &mut Cx,
        _id: &mut Id,
        state: &mut Self::State,
        element: &mut Self::Element,
    ) -> ChangeFlags {
        let mut pod_slice = PodSlice::new(&mut element.els);
        self.children
            .rebuild(&prev.children, cx, state, &mut pod_slice)
    }

    fn message(
        &self,
        id_path: &[Id],
        state: &mut Self::State,
        event: Box<dyn Any>,
        app_state: &mut T,
    ) -> EventResult<A> {
        self.children.message(id_path, event, state, app_state)
    }
}
